﻿namespace UFrame
{
    public class FSM<T>
    {
        private T stateEntity;
        private IFSMState<T> currentState;
        private IFSMState<T> previousState;
        private IFSMState<T> autoChangeState;
        private IFSMState<T> anyState;


        public FSM(T inst)
        {
            stateEntity = inst;
        }

        public string GetCurrentName()
        {
            if (currentState != null)
            {
                return currentState.GetType().Name;
            }

            return string.Empty;
        }

        public bool IsCurrentState(IFSMState<T> state)
        {
            if (currentState == null)
            {
                return false;
            }

            return currentState.Equals(state);
        }


        public void SetPreviousState(IFSMState<T> state)
        {
            previousState = state;
        }

        // called by T
        public void Update()
        {
            if (autoChangeState != null)
            {
                ChangeState(autoChangeState);
                autoChangeState = null;
                return;
            }

            if (anyState != null)
            {
                anyState.Execute(stateEntity);
            }

            if (currentState != null)
            {
                currentState.Execute(stateEntity);
            }
        }

        public void AutoChangeState(IFSMState<T> state)
        {
            autoChangeState = state;
        }

        public void AnyState(IFSMState<T> state)
        {
            anyState = state;
        }

        public void ChangeState(IFSMState<T> state)
        {
            if (state == null)
            {
                //      Debug.LogError("The state would be switched is null");
                return;
            }

            autoChangeState = null;
            if (currentState != state)
            {
                previousState = currentState;
            }

            if (currentState != null)
            {
                currentState.Exit(stateEntity);
            }

            currentState = state;
            currentState.Enter(stateEntity);
        }

        public void RevertToPreviousState()
        {
            ChangeState(previousState);
        }

        public bool IsInState(IFSMState<T> state)
        {
            return currentState.GetType() == state.GetType();
        }

        public void Dispose()
        {
            currentState = null;
            previousState = null;
            autoChangeState = null;
        }
    }
}